#include "tools.hpp"
#include <glad/glad.h>
#include <string>
#include <fstream>

using namespace std;

string readFile(string_view path)
{
    string content;
    ifstream file(path.data());
    if (!file.is_open()) {
        throw runtime_error("Could not open file" + string(path));
    }
    string line;
    while (getline(file, line)) {
        content += line + "\n";
    }
    return content;
}

// 工具函数：打印着色器编译日志
void printShaderLog(GLuint shader) {
    GLint logLength = 0;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 1) {
        std::vector<GLchar> log(logLength);
        glGetShaderInfoLog(shader, logLength, nullptr, log.data());
        std::cerr << "Shader log:\n" << log.data() << std::endl;
    }
}

// 工具函数：编译着色器
GLuint compileShader(GLenum type, const std::string_view src) {
    GLuint shader = glCreateShader(type);
    const char* cstr = src.data();
    glShaderSource(shader, 1, &cstr, nullptr);
    glCompileShader(shader);

    GLint status = GL_FALSE;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE) {
        printShaderLog(shader);
        throw std::runtime_error("Shader compilation failed");
    }
    return shader;
}

// 工具函数：创建着色器程序
GLuint createProgram(std::string_view vsSrc, std::string_view fsSrc) {
    auto s1 = readFile(vsSrc);
    auto s2 = readFile(fsSrc);
    GLuint vs = compileShader(GL_VERTEX_SHADER, s1);
    GLuint fs = compileShader(GL_FRAGMENT_SHADER, s2);

    GLuint program = glCreateProgram();
    glAttachShader(program, vs);
    glAttachShader(program, fs);
    glLinkProgram(program);

    GLint status = GL_FALSE;
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    if (status != GL_TRUE) {
        GLint logLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 1) {
            std::vector<GLchar> log(logLength);
            glGetProgramInfoLog(program, logLength, nullptr, log.data());
            std::cerr << "Program link log:\n" << log.data() << std::endl;
        }
        throw std::runtime_error("Program linking failed");
    }

    glDeleteShader(vs);
    glDeleteShader(fs);
    return program;
}

